var bound = { // 函数显示的区间
    xFrom: -10,
    xTo: 10,
    yFrom: -10,
    yTo: 10,
    zFrom: -10,
    zTo: 10,
};

var realityBound = { // webgl的区间
    xFrom: -100,
    xTo: 100,
    yFrom: -100,
    yTo: 100,
    zFrom: -100,
    zTo: 100,
};

function xZoom(iOverride) // x轴放大缩小
{
    bound.xFrom = bound.xFrom * iOverride;
    bound.xTo = bound.xTo * iOverride;
    reBuild();
    updateGui();
}

function yZoom(iOverride) // y轴放大缩小
{
    bound.yFrom = bound.yFrom * iOverride;
    bound.yTo = bound.yTo * iOverride;
    reBuild();
    updateGui();
}

function zZoom(iOverride) // z轴放大缩小
{
    bound.zFrom = bound.zFrom * iOverride;
    bound.zTo = bound.zTo * iOverride;
    reBuild();
    updateGui();
}

function zoom(iOverride) // 一起放大缩小
{
    bound.xFrom = bound.xFrom * iOverride;
    bound.xTo = bound.xTo * iOverride;
    bound.yFrom = bound.yFrom * iOverride;
    bound.yTo = bound.yTo * iOverride;
    bound.zFrom = bound.zFrom * iOverride;
    bound.zTo = bound.zTo * iOverride;
    reBuild();
    updateGui();
}

boundPlanes = [new THREE.Plane(new THREE.Vector3(0, 1, 0), 100),
               new THREE.Plane(new THREE.Vector3(0, -1, 0), 100)]

let override; // 现实 / 函数区间 倍率，用于将函数计算结果放大或缩小，填充到指定的范围内
updateVar();
function updateVar() { // 更新变量
    override =  (realityBound.yTo - realityBound.yFrom) / (bound.yTo - bound.yFrom);
}

var variables = new Map(); // 变量

function reBuild() {
    updateVar();
    params.xResolution = Math.round(params.xResolution);
    params.zResolution = Math.round(params.zResolution);
    scene.remove(params.mesh);
    scene.remove(params.line);
    params.update();
    scene.add(params.mesh);
    if (params.drawLine) {
        scene.add(params.line);
    }
}

params = { // 函数的参数
    func: "x * x + z * z",
    xResolution: 20,
    zResolution: 20,
    lut: new THREE.Lut(),
    firstColor: "#ffd700",
    lastColor: "#00aaff",
    colorMap: "normal",
    materialParams: {
        side: THREE.DoubleSide,
        clippingPlanes: boundPlanes,
        // vertexColors: true,
        color: "#ffd700",
    },
    mesh: undefined,
    clippingFromPlanes: true,
    clippingFromCalc: false,
    drawLine: false,
    update: function() {
        this.geometry = eval3df(this);

        // let colors = [];
        // for (let i = 0, n = this.geometry.attributes.position.count; i < n; ++ i) {
        //     colors.push(1, 1, 1);
        // }
        // this.geometry = this.geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
        this.wireframe = new THREE.WireframeGeometry(this.geometry);
        this.line = new THREE.LineSegments(this.wireframe);
        this.line.material.depthTest = true;
        this.line.material.opacity = 0.25;
        this.line.material.transparent = false;

        if (this.clippingFromPlanes) {
            this.materialParams.clippingPlanes = boundPlanes;
            this.line.material.clippingPlanes = boundPlanes;
        } else {
            this.materialParams.clippingPlanes = [];
        }
        this.material = new THREE.MeshPhongMaterial(this.materialParams);
        this.mesh = new THREE.Mesh(this.geometry, this.material);

        

        // this.lut.addColorMap("normal", [[0.0, eval("0x" + params.firstColor.substring(1))], [1.0, eval("0x" + params.lastColor.substring(1))]]);
        // this.lut.setColorMap(this.colorMap);
		// this.lut.setMax(realityBound.yFrom - 1);
        // this.lut.setMin(realityBound.yTo + 1);
        // let meshGeometry = this.mesh.geometry;
        // let pressures = meshGeometry.attributes.position;
        // colors = meshGeometry.attributes.color;
        // for (let i = 0; i < meshGeometry.attributes.position.array.length; i ++) {
        //     let colorValue = pressures.array[i];
        //     let color = this.lut.getColor(colorValue);
        //     if (color === undefined) {
        //         console.log("colorValue", colorValue, "cannot find");
        //         color = this.lut.getColor(realityBound.yTo);
        //     } else {
        //         colors.setXYZ(i, color.r, color.g, color.b);
        //     }
        //     i+=2;
        // }
        // colors.needsUpdate = true;
    },
    build: reBuild,
}



function eval3df(inputParams) {
    let func = "" + inputParams.func;
    variables.forEach(function(value, key) { // 将字符串中的变量替换为对应的数字（或表达式）
        func = func.replace(key, value);
    })
    console.log("eval the function:", func);

    let node = math.parse(func);
    let code = node.compile(); // 编译函数

    function getPoint(u, v, target) { // u，v为0~1区间的数。需要在target中修改x,y,z
        // console.log("u", u, "v", v);
        // return new THREE.Vector4(u, 100, v, 1);
        let scope = { // 真实情况
            x: bound.xFrom + u * (bound.xTo - bound.xFrom),
            z: bound.zFrom + v * (bound.zTo - bound.zFrom)
        }

        let realityScope = { // webgl情况
            x: realityBound.xFrom + u * (realityBound.xTo - realityBound.xFrom),
            z: realityBound.zFrom + v * (realityBound.zTo - realityBound.zFrom)
        }
        let value = code.evaluate(scope); // 计算
        // console.assert(typeof(value) === "number", "函数样式错误：输出包括非正常数字（例如复数等），无法渲染到WebGL上。");
        // if (isNaN(value) || typeof(value) !== "number") {
        //     value = 0;
        // }

        // if (isFinite(value) && value > 0) {
        //     value = 1e16;
        // }

        // if (isFinite(value) && value < 0) {
        //     value = -1e16;
        // }

        if (inputParams.clippingFromCalc) {
            if (value > bound.yTo) {
                value = bound.yTo;
            }

            if (value < bound.yFrom) {
                value = bound.yFrom;
            }
        }

        target.x = realityScope.x;
        target.y = value * override + (realityBound.yTo + realityBound.yFrom) / 2;
        target.z = realityScope.z;
        // console.log(target);
    }
    let geometry = new THREE.ParametricBufferGeometry(getPoint, inputParams.xResolution, inputParams.zResolution);
    // for (let i = 0; i <= inputParams.xResolution; i++) {
    //     for (let j = 0; j <= inputParams.zResolution; j++) {
    //         let scope = {
    //             x: bound.xFrom + i * xStep,
    //             z: bound.zFrom + j * zStep
    //         }
    //         let value = code.evaluate(scope);
    //         console.assert(typeof(value) === "number", "函数样式错误：输出包括非正常数字（例如复数等），无法渲染到WebGL上。"); 
    //     }
    // }

    let op = new THREE.Vector3();
    console.log(getPoint(0.5, 0.5, op));
    console.log(op);

    return geometry;
}
function updateGui() {
    girdGuiController.xFrom.setValue(bound.xFrom);
    girdGuiController.xTo.setValue(bound.xTo);
    girdGuiController.yFrom.setValue(bound.yFrom);
    girdGuiController.yTo.setValue(bound.yTo);
    girdGuiController.zFrom.setValue(bound.zFrom);
    girdGuiController.zTo.setValue(bound.zTo);
}